<template>
  <div class="data-standard">
    <div ref="chart" style="width: 100%; height: 100%"></div>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import { getTextLen, subTextLen } from '@/utils/util/format'

export default {
  name: 'DataStandardTree',
  props: {
    highlightNodes: {
      type: Array,
      default: () => []
    },
    treeData: {
      type: Object,
      default: () => {}
    },
    highlightStyle: {
      type: Object,
      default: () => ({
        lineStyle: { color: '#B5C8FF' },
        label: {
          rich: {
            a: {
              color: '#3366FF',
              borderColor: '#B5C8FF',
              backgroundColor: '#F3F6FF'
            }
          }
        }
      })
    }
  },
  data() {
    return {
      chart: null,
      data: this.treeData
    }
  },
  watch: {
    treeData() {
      this.data = this.treeData
      this.updateChart()
    },
    highlightNodes() {
      this.updateChart()
    }
  },
  mounted() {
    this.init()
    // 屏幕缩放的时候，重绘echart
    window.addEventListener('resize', () => {
      if (this.chart) {
        this.chart.resize()
      }
    })
  },
  unmounted() {
    this.destroyChart()
  },
  methods: {
    init() {
      if (!this.data) {
        return
      }

      this.setHighlightStyle()
      this.chart = echarts.init(this.$refs.chart)
      const currentOptions = this.buildOption()
      this.chart.setOption(currentOptions)
    },
    buildOption() {
      return {
        grid: {
          left: 0,
          top: 0,
          right: 0,
          bottom: 0
        },
        tooltip: {
          show: true,
          trigger: 'item',
          triggerOn: 'mousemove'
        },
        series: [
          {
            type: 'tree',
            data: [this.data],
            initialTreeDepth: 3, // 默认树展开的层数
            expandAndCollapse: true,
            top: 0,
            left: 60,
            bottom: 0,
            right: 140,
            symbol: 'roundRect',
            symbolSize: 24,
            itemStyle: {
              color: 'transparent'
            },
            tooltip: {
              formatter: function (params) {
                return `<div class="tooltip" style="padding:0"><div>${
                  params.data.key + ' ' + params.name
                }</div><div>${(params.data.description || '').replace(
                  /\n/g,
                  '<br/>'
                )}</div></div>`
              }
            },
            label: {
              formatter: function (params) {
                const text = params.data.key + ' ' + params.name
                const t =
                  getTextLen(text) <= 20 ? text : `${subTextLen(text, 20)}...`
                return '{a|' + t + '}'
              },
              position: [-30, 0],
              rich: {
                a: {
                  padding: [5, 8, 5, 8],
                  borderRadius: 2,
                  color: '#262626',
                  fontSize: 14,
                  backgroundColor: '#fff',
                  borderColor: '#d9d9d9',
                  borderWidth: 1
                }
              }
            },
            lineStyle: {
              // 非叶子节点的连线样式
              color: '#d9d9d9',
              type: 'polyline',
              width: 1,
              curveness: 0.5 // 可选，设置连线曲度
            },
            animationDurationUpdate: 750
          }
        ]
      }
    },
    destroyChart() {
      if (!this.chart) {
        return
      }
      this.chart.dispose()
      this.chart = null
    },
    updateChart() {
      this.destroyChart()
      this.init()
    },
    /**
     * 设置高亮节点的样式 和 默认展开的节点
     * 默认展开判断条件：
     * 1. 层级小于4，即与根节点的距离小于3
     * 2. 当前节点在高亮路径上
     */
    setHighlightStyle() {
      const highlightKeys = this.highlightNodes.reduce((prev, cur) => {
        const path = this.findHighlightPath(cur)
        return prev.concat(path)
      }, [])
      let level = 0
      const dfs = (node) => {
        if (!node) {
          return
        }

        level += 1
        node.value = node.label
        if (highlightKeys.includes(node.key)) {
          node.lineStyle = this.highlightStyle.lineStyle
          node.label = this.highlightStyle.label
        } else {
          node.lineStyle = {}
          node.label = {}
        }

        // 设置节点是否默认展开
        if (level < 4 || highlightKeys.includes(node.key)) {
          node.collapsed = false
        } else {
          node.collapsed = true
        }

        if (!node.children) {
          return
        }

        node.children.forEach((item) => dfs(item))
        level -= 1
      }
      dfs(this.data)
    },
    /**
     * 找出需要高亮展示的节点路径（key集合）
     */
    findHighlightPath(key) {
      let result = []
      const path = []
      const dfs = (node) => {
        path.push(node.key)
        if (node.key === key) {
          result = [...path]
          return
        }
        if (!node.children?.length) {
          path.pop()
          return
        }

        node.children.forEach((item) => {
          dfs(item)
        })
        path.pop()
      }
      dfs(this.treeData)
      return result
    }
  }
}
</script>

<style scoped lang="scss">
.data-standard {
  position: relative;
  width: 100%;
  height: 100%;
  background-color: #fff;
}
</style>
